
package com.seekting.gongzhu.serversdk;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

import com.seekting.gongzhu.sdk.ConnectListener;
import com.seekting.gongzhu.sdk.ConnectListener.ConnectResult;
import com.seekting.gongzhu.sdk.Connectedable;
import com.seekting.gongzhu.sdk.Info;
import com.seekting.gongzhu.sdk.KLog;
import com.seekting.gongzhu.sdk.NetWorkHelper;

public class Host implements Connectedable {
    public static final String UDP_GET_IP_REQUEST = "get_ip";
    public static final int UDP_GET_IP_REQUEST_LENGTH = UDP_GET_IP_REQUEST.getBytes().length;
    public static int MAX_JION_SIZE = 4;

    private ServerSocket mServerSocket;

    private Thread tcpNetWorkThread;
    private Thread udpNetWorkThread;
    private DatagramSocket datagramSocket;

    private Map<String, HostNetWorkHelper> hostNetWorkHelpsers;
    private ConnectListener connectedListener;

    public Host() {

    }

    @Override
    public synchronized void prepare() {

        hostNetWorkHelpsers = new HashMap<String, HostNetWorkHelper>();
        KLog.d("server acceptTcp");
        try {
            mServerSocket = new ServerSocket(Info.HOST_PORT);
            mServerSocket.setReuseAddress(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public synchronized void closeListen() {

        if (datagramSocket != null) {
            datagramSocket.close();
        }
        if (mServerSocket != null) {
            try {
                mServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        KLog.d("closeListen");
    }

    @Override
    public synchronized boolean bind(ConnectListener connectedListener) {
        if (this.connectedListener != null) {
            return false;
        }
        this.connectedListener = connectedListener;

        return true;
    }

    public synchronized void listen() {
        tcpNetWorkThread = new Thread(new Runnable() {

            @Override
            public void run() {
                acceptTcp();
                KLog.d("tcp listen over");
            }

        });
        udpNetWorkThread = new Thread(new Runnable() {

            @Override
            public void run() {
                acceptUDP();
                KLog.d("udp listen over");
            }
        });
        udpNetWorkThread.start();
        tcpNetWorkThread.start();
    }

    public synchronized void unBind(ConnectListener connectedListener) {
        if (this.connectedListener == connectedListener) {
            this.connectedListener = null;
        }
    }

    private void acceptUDP() {
        try {
            datagramSocket = new DatagramSocket(Info.UDP_PORT);
            while (true) {
                byte[] bytes = new byte[UDP_GET_IP_REQUEST_LENGTH];
                DatagramPacket data = new DatagramPacket(bytes, UDP_GET_IP_REQUEST_LENGTH);
                datagramSocket.receive(data);
                SocketAddress address = data.getSocketAddress();

                String recStr = new String(bytes);
                if (UDP_GET_IP_REQUEST.equals(recStr)) {
                    byte[] ipByte = UDP_GET_IP_REQUEST.getBytes();

                    DatagramPacket sendPack = new DatagramPacket(ipByte, ipByte.length, address);
                    datagramSocket.send(sendPack);
                }
            }

        } catch (SocketException e) {
            e.printStackTrace();
            KLog.e("udp异常退出" + e);
        } catch (IOException e) {
            KLog.e("udp异常退出" + e);
        }

    }

    private void acceptTcp() {
        try {

            while (true) {
                Socket socket = mServerSocket.accept();
                DataInputStream in = new DataInputStream(socket.getInputStream());
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                HostNetWorkHelper hostNetWorkHelper = new HostNetWorkHelper(socket, out, in, 0,
                        Host.this, Host.this);
                final String ipPort = hostNetWorkHelper.getTargetIp();

                ConnectResult connectResult = null;
                synchronized (Host.this) {

                    if (connectedListener == null) {
                        hostNetWorkHelper.refuse(Info.ErrorCode.NO_GAME_JOIN);
                    } else {
                        connectResult = connectedListener.tryConnect(ipPort);
                        
                    }
                }
                if (connectResult != null) {
                    switch (connectResult) {
                        case Success:
                            hostNetWorkHelpsers.put(ipPort, hostNetWorkHelper);
                            hostNetWorkHelper.startRecMsg(Host.this);
                            connectedListener.ConnectSuc(ipPort);
                            break;
                        case FailDuplicateJoin:
                            hostNetWorkHelper.refuse(Info.ErrorCode.DUPLICATE_JOIN);
                            break;
                        case FailNoEmptyPosition:
                            hostNetWorkHelper.refuse(Info.ErrorCode.NO_EMPTY_POSITION);
                            break;
                        default:
                            break;
                    }
                }
            }
        } catch (IOException e) {
            KLog.e("Tcp异常退出");
        }
    }

    // public void sendRole(int i) {
    // RoleJson roleJson = new RoleJson();
    // roleJson.setRole(i);
    // client[i].send(roleJson);
    // }

    // public void sendTo(ActionJson json, int i) {
    // if (client.length > i) {
    // client[i].send(json);
    // } else {
    // KLog.e("no client!");
    // }
    // }

    @Override
    public void onDisConnect(int mIndex, String ipPort) {
        hostNetWorkHelpsers.remove(ipPort);

    }

    @Override
    public void send(String ip, String str) {
        NetWorkHelper netWorkHelper = hostNetWorkHelpsers.get(ip);
        if (netWorkHelper != null) {
            System.out.println("发消息！");
            netWorkHelper.send(str);
        }

    }

    @Override
    public void onReceive(String ip, String str) {
        // TODO Auto-generated method stub

    }

}
